home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr01 / jock.zip / TOTSRC11.ZIP / TOTMENU.PAS < prev    next >
Pascal/Delphi Source File  |  1993-06-08  |  56KB  |  2,056 lines

  1. {               Copyright 1991 TechnoJock Software, Inc.               }
  2. {                          All Rights Reserved                         }
  3. {                         Restricted by License                        }
  4.  
  5. {                             Build # 1.10b                            }
  6.  
  7. Unit totMENU;
  8. {$I TOTFLAGS.INC}
  9.  
  10. {
  11.  Development Notes:
  12.           Mar 10, 1991  1.00a   Enabled immediate selection
  13.                                 when no sub menu.
  14.           Apr  4, 1991  1.00b   Modified EZPULL.Done
  15.           Apr 22, 1991  1.00c   corrected '=' topic
  16.           Apr 26, 1991  1.00d   corrected message clearing
  17.           May  3, 1991  1.00e              ""
  18.           May  7, 1991  1.00f   allowed setting of sub-menus XY
  19.           May 23, 1991  1.00g   Added reaction to Mouse method 1
  20.           Jun 24, 1991  1.00h   Cleared Lotus menu when sub called
  21.           Jul 24, 1991  1.00i   Hide non-selectable items from mouse clicks
  22.           Jan 23, 1992  1.00j   Checked active status in hotkey selection
  23.           Oct  2, 1992  1.00k   Corrected menu clearing in LotusMenuOBJ
  24.           Jan  4, 1993  1.10    Corrected Range Check error on Pullmenus
  25.           May  3, 1993  1.10a   Restored menu message when sub-sub removed
  26.           May  9, 1993  1.10b   Allowed for an empty drop-down.
  27.                                 Thanks to Arnold Gordijn!
  28. }
  29.  
  30. INTERFACE
  31.  
  32. uses DOS, CRT,
  33.      totLOOK, totSYS, totINPUT, totFAST, totWIN, totSTR, totIO1, totLINK;
  34.  
  35. CONST
  36.    EscapeID = 65535;
  37.    LeftID   = 65534;
  38.    RightID  = 65533;
  39.    DriftID  = 65532;
  40.  
  41. TYPE
  42. BaseMenuPtr = ^BaseMenuOBJ;         
  43. MenuItemPtr = ^MenuItem;
  44. MenuItem = record
  45.    NextNode: MenuItemPtr;
  46.    TxtPtr: pointer;
  47.    MsgPtr: pointer;
  48.    HK: word;
  49.    ID: word;
  50.    Active: boolean;
  51.    SubMenu:  BaseMenuPtr;
  52. end;
  53.  
  54. pBaseMenuOBJ = ^BaseMenuOBJ;
  55. BaseMenuOBJ = object
  56.    vItemStack: MenuItemPtr;
  57.    vTotalItems: byte;
  58.    vActiveItem: byte;
  59.    vGap: byte;
  60.    vMsgX: byte;
  61.    vMsgY: byte;
  62.    vX: byte;
  63.    vY: byte;
  64.    vWidth: byte;
  65.    vLastKey: word;
  66.    vAllowEsc: boolean;
  67.    vUsedInPull: boolean;
  68.    vPickOff: boolean;
  69.    vSubActive: boolean;
  70.    vMenuHiHot: byte;
  71.    vMenuHiNorm: byte;
  72.    vMenuLoHot: byte;
  73.    vMenuLoNorm: byte;
  74.    vMenuOff: byte;
  75.    vHelpHook:  HelpProc;
  76.    vHelpKey: word;
  77.    vMsgVisible: boolean;
  78.    {methods...}
  79.    constructor Init;
  80.    procedure   AddFullItem(Txt:StrVisible; ID,HK:word; Msg:StrVisible; SubM:BaseMenuPtr);
  81.    procedure   AddItem(Txt:StrVisible);
  82.    procedure   SetTopic(Item:byte; Txt:StrVisible);
  83.    procedure   SetHK(Item:byte; HK:word);
  84.    procedure   SetMessage(Item:byte; Msg:StrVisible);
  85.    procedure   SetID(Item:byte; ID:word);
  86.    procedure   SetStatus(Item:byte; On:boolean);
  87.    procedure   SetSubMenu(Item:byte;SubMenu:BaseMenuPtr);
  88.    procedure   SetGap(G:byte);
  89.    procedure   SetActiveItem(Item:byte);
  90.    procedure   SetMessageXY(X,Y:byte);
  91.    procedure   SetMenuXY(X,Y:byte);
  92.    procedure   SetHelpKey(K:word);
  93.    procedure   SetHelpHook(Proc:HelpProc);
  94.    procedure   SetAllowEsc(On:boolean);
  95.    procedure   SetColors(HiHot,HiNorm,LoHot,LoNorm,Off:byte);
  96.    procedure   TurnPickOff;
  97.    function    GetAllowEsc: boolean;
  98.    function    GetText(Ptr:MenuItemPtr): StrVisible;
  99.    function    GetMessage(Ptr:MenuItemPtr): StrVisible;
  100.    function    GetID(Item:byte):word;
  101.    function    GetActiveItem: byte;
  102.    function    GetTotalItems: byte;
  103.    function    GetPickOff: boolean;
  104.    function    GetSubActive:boolean;
  105.    procedure   DisplayAllItems;
  106.    function    HotkeySelect(K:word): boolean;
  107.    procedure   ChangeActiveItem(New:byte);
  108.    function    FirstActiveItem: byte;
  109.    function    AddPre(Txt:StrVisible;Hi:boolean):StrVisible;
  110.    function    AddSuf(Txt:StrVisible;Hi:boolean):StrVisible;
  111.    function    ItemPtr(Item:byte): MenuItemPtr;
  112.    procedure   DisposeItems;
  113.    procedure   ChangeMessage(Item:byte; Hi:boolean);
  114.    function    LastKey: word;
  115.    function    GetHelpID: word;
  116.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL;
  117.    function    MenuZone(X,Y:byte):boolean;                       VIRTUAL;
  118.    procedure   SetForPull;                                       VIRTUAL;
  119.    function    TargetPick(X,Y:byte): byte;                       VIRTUAL;
  120.    procedure   DisplayItem(Item:byte;Hi,Msg:boolean);            VIRTUAL;
  121.    procedure   Remove;                                           VIRTUAL;
  122.    function    Activate: word;                                   VIRTUAL;
  123.    procedure   DrawEngine(eX,eY:byte);                           VIRTUAL;
  124.    procedure   HelpTask(ID:word);                                VIRTUAL;
  125.    destructor  Done;                                             VIRTUAL;
  126.    end; {BaseMenuOBJ}
  127.  
  128. pWinMenuOBJ = ^WinMenuOBJ;
  129. WinMenuOBJ = object (BaseMenuOBJ)
  130.    vStyle: byte;
  131.    vWinSaved: boolean;
  132.    vMenuBorder: byte;
  133.    vMenuTitle: byte;
  134.    vMenuIcons: byte;
  135.    {methods...}
  136.    constructor Init;
  137.    procedure   SetStyleTitle(St:byte;Tit:StrVisible);
  138.    procedure   Draw;
  139.    procedure   MoveUp;
  140.    procedure   MoveDown;
  141.    procedure   MoveHome;
  142.    procedure   MoveEnd;
  143.    function    MousePressed(X,Y:byte):boolean;
  144.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL;
  145.    function    MenuZone(X,Y:byte):boolean;                       VIRTUAL;
  146.    procedure   SetForPull;                                       VIRTUAL;
  147.    function    TargetPick(X,Y:byte): byte;                       VIRTUAL;
  148.    procedure   DisplayItem(Item:byte;Hi,Msg:boolean);            VIRTUAL;
  149.    procedure   Remove;                                           VIRTUAL;
  150.    function    Activate: word;                                   VIRTUAL;
  151.    procedure   DrawEngine(eX,eY:byte);                           VIRTUAL;
  152.    function    Win: WinPtr;                                      VIRTUAL;
  153.    destructor  Done;                                             VIRTUAL;
  154. end; {WinMenuOBJ}
  155.  
  156. SubMenuPtr = ^MenuOBJ;
  157. pMenuOBJ = ^MenuOBJ;
  158. MenuOBJ = object (WinMenuOBJ)
  159.    vWin: WinPtr;
  160.    {methods...}
  161.    constructor Init;
  162.    function    Win: WinPtr;                                      VIRTUAL;
  163.    destructor  Done;                                             VIRTUAL;
  164. end; {MenuOBJ}
  165.  
  166. pMoveMenuOBJ = ^MoveMenuOBJ;
  167. MoveMenuOBJ = object (WinMenuOBJ)
  168.    vWin: MoveWinPtr;
  169.    {methods...}
  170.    constructor Init;
  171.    function    Win: WinPtr;                                      VIRTUAL;
  172.    destructor  Done;                                             VIRTUAL;
  173. end; {MoveMenuOBJ}
  174.  
  175. pBarMenuOBJ = ^BarMenuOBJ;
  176. BarMenuOBJ = object (BaseMenuOBJ)
  177.    {methods...}
  178.    constructor Init;
  179.    function    GetX(Item:byte): byte;
  180.    procedure   DisplayItem(Item:byte;Hi,Msg:boolean);            VIRTUAL;
  181.    procedure   DrawEngine(eX,eY:byte);                           VIRTUAL;
  182.    destructor  Done;                                             VIRTUAL;
  183. end; {BarMenuOBJ}
  184.  
  185. BarHotKeyPtr = ^BarHotKeyItem;
  186. BarHotKeyItem = record
  187.    HK:word;
  188.    ID:word;
  189.    NextNode: BarHotKeyPtr;
  190. end; {BarHotKeyRecord}
  191.  
  192. pLotusMenuOBJ = ^LotusMenuOBJ;
  193. LotusMenuOBJ = object (BarMenuOBJ)
  194.    vHKStack: BarHotKeyPtr;
  195.    vMenuBarVisible: boolean;
  196.    {methods...}
  197.    constructor Init;
  198.    procedure   Draw;
  199.    procedure   MoveLeft;
  200.    procedure   MoveRight;
  201.    procedure   MoveHome;
  202.    procedure   MoveEnd;
  203.    procedure   SetSpecialKey(HK:word;ID:word);
  204.    function    HotKeyID(HK:word):word;
  205.    function    GetHK(Item:byte):word;
  206.    procedure   DisposeSpecialKeys;
  207.    function    AltHKItem(K:word):word;
  208.    function    MenuKey(K:word; X,Y:byte): boolean;
  209.    function    MousePressed(X,Y:byte;var Choice:word):boolean;
  210.    function    Push(K:word; X,Y:byte): word;
  211.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL;
  212.    function    TargetPick(X,Y:byte): byte;                       VIRTUAL;
  213.    procedure   Remove;                                           VIRTUAL;
  214.    function    Activate: word;                                   VIRTUAL;
  215.    destructor  Done;                                             VIRTUAL;
  216. end; {LotusMenuOBJ}
  217.  
  218. pPullMenuOBJ = ^PullMenuOBJ;
  219. PullMenuOBJ = object (LotusMenuOBJ)
  220.    vMenuDown: boolean;
  221.    {methods...}
  222.    constructor Init;
  223.    procedure   MoveLeft;
  224.    procedure   MoveRight;
  225.    procedure   MoveHome;
  226.    procedure   MoveEnd;
  227.    function    MousePressed(X,Y:byte):boolean;
  228.    function    Push(K:word; X,Y:byte): word;
  229.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL;
  230.    function    Activate: word;                                   VIRTUAL;
  231.    destructor  Done;                                             VIRTUAL;
  232. end; {PullMenuOBJ}
  233.  
  234. SubMenuListPtr = ^SubMenuList;
  235. SubMenuList = record
  236.    SubMenu: SubMenuPTR;
  237.    NextMenu: SubMenuListPtr;
  238. end;
  239.  
  240. pEZPullOBJ = ^EZPullOBJ;
  241. EZPullOBJ = object
  242.    vTopBar: pPullMenuOBJ;
  243.    vSubMenuStack: SubMenuListPtr;
  244.    vListAssigned: boolean;
  245.    vTotalSubs: byte;
  246.    {methods...}
  247.    constructor Init;
  248.    function    Activate: word;                                  
  249.    procedure   BuildMenu;
  250.    function    MainMenu:pPullMenuOBJ;
  251.    function    SubMenu(MenuNumber: byte):SubMenuPtr; 
  252.    function    Push(K:word; X,Y:byte): word;
  253.    function    TotalStrings: word;                               VIRTUAL;
  254.    function    GetString(Item: word): string;                    VIRTUAL; 
  255.    destructor  Done;                                             VIRTUAL;
  256. end; {EZPullOBJ}
  257.  
  258. pEZPullArrayOBJ = ^EZPullArrayOBJ;
  259. EZPullArrayOBJ = object (EZPullOBJ)
  260.    vTotalItems: byte;
  261.    vArrayPtr: pointer;
  262.    vStrLength: byte;
  263.    {methods...}
  264.    constructor Init;
  265.    procedure   AssignList(var StrArray; Total:Longint; StrLength:byte);
  266.    function    TotalStrings: word;                               VIRTUAL;
  267.    function    GetString(Item: word): string;                    VIRTUAL;
  268.    destructor  Done;                                             VIRTUAL;
  269. end; {EZPullArrayOBJ}
  270.  
  271. pEZPullLinkOBJ = ^EZPullLinkOBJ;
  272. EZPullLinkOBJ = object (EZPullOBJ)
  273.    vLinkList: ^DLLOBJ;
  274.    {methods...}
  275.    constructor Init;
  276.    procedure   AssignList(var LinkList: DLLOBJ);
  277.    function    TotalStrings: word;                               VIRTUAL;
  278.    function    GetString(Item: word): string;                    VIRTUAL;
  279.    destructor  Done;                                             VIRTUAL;
  280. end; {EZPullLinkOBJ}
  281.  
  282. procedure menuINIT;
  283.  
  284. IMPLEMENTATION
  285. Const
  286.    EZSeparator:char = '"';
  287.    EZInActive: char = '_';
  288.    EZNewBarItem: char = '\';
  289.  
  290. procedure Error(Err:byte);
  291. {routine to display error}
  292. const
  293.    Header = 'totMENU error: ';
  294. var
  295.    Msg : string;
  296. begin
  297.    Case Err of
  298.    1: Msg := 'Not enough memory to create menu';
  299.    else  Msg := 'Unknown Error';
  300.    end; {case}
  301.    Writeln(Header,Msg);
  302.    halt;
  303. end; {Error}
  304. {|||||||||||||||||||||||||||||||||||||||||||||||}
  305. {                                               }
  306. {     B a s e M e n u O B J   M E T H O D S     }
  307. {                                               }
  308. {|||||||||||||||||||||||||||||||||||||||||||||||}
  309. {$I TOTMENU.INC}
  310. {|||||||||||||||||||||||||||||||||||||||||||||}
  311. {                                             }
  312. {     W i n M e n u O B J   M E T H O D S     }
  313. {                                             }
  314. {|||||||||||||||||||||||||||||||||||||||||||||}
  315. constructor WinMenuOBJ.Init;
  316. {}
  317. begin
  318.    BaseMenuOBJ.Init;
  319.    vWinSaved := false;
  320.    vStyle := 6;
  321.    vGap := 2;
  322. end; {WinMenuOBJ.Init}
  323.  
  324. procedure WinMenuOBJ.SetStyleTitle(St:byte;Tit:StrVisible);
  325. {}
  326. begin
  327.    vStyle := St;
  328.    Win^.SetTitle(Tit);
  329. end; {WinMenuOBJ.SetStyle}
  330.  
  331. procedure WinMenuOBJ.SetForPull;
  332. {}
  333. begin
  334.    SetStyleTitle(1,'');
  335.    SetGap(0);
  336.    Win^.SetClose(False);
  337.    vUsedInPull := true;
  338.    vMsgX := 11;
  339.    vMsgY := Monitor^.Depth;
  340. end; {WinMenuOBJ.SetForPull}
  341.  
  342. function WinMenuOBJ.Win: WinPtr;
  343. {abstract} begin end;
  344.  
  345. function WinMenuOBJ.MenuZone(X,Y:byte): boolean;
  346. {}
  347. var 
  348.    X1,Y1,X2,Y2,style: byte;
  349.    InZone: boolean;
  350. begin
  351.    if (ItemPtr(vActiveItem) <> nil) and (ItemPtr(vActiveItem)^.SubMenu <> nil) then
  352.       InZone := ItemPtr(vActiveItem)^.SubMenu^.MenuZone(X,Y)
  353.    else
  354.       InZone := false;
  355.    if not InZone then
  356.    begin
  357.       Win^.GetSize(X1,Y1,X2,Y2,Style);
  358.       InZone := vWinsaved and (X >= X1) and (X <= X2) and (Y >= Y1) and (Y <= Y2);
  359.    end;
  360.    MenuZone := InZone;
  361. end; {WinMenuOBJ.MenuZone}
  362.  
  363. procedure WinMenuOBJ.DisplayItem(Item:byte;Hi,Msg:boolean);
  364. {}
  365. var               
  366.    Hot,Norm: byte;
  367.    Temp: MenuItemPtr;
  368.    Txt: StrVisible;
  369.    WinWasActive: boolean;
  370.  
  371.    procedure DrawLine(S:byte);
  372.    {}
  373.    const
  374.      Single: string[2] = '├┤';
  375.      Double: string[2] = '╞╡';
  376.    var
  377.      X1,Y1,X2,Y2,Style,Att: byte;
  378.      Ends: string[2];
  379.    begin
  380.      Win^.GetSize(X1,Y1,X2,Y2,Style);
  381.      if not (Style in [0,6]) then
  382.      begin
  383.         if S = 1 then
  384.            Ends := Single
  385.         else
  386.            Ends := Double;
  387.         Att := LookTOT^.MenuBor;
  388.         WinWasActive := Screen.WindowOff;
  389.         Y1 := Y1 + Item;
  390.         Screen.WriteAt(X1,Y1,Att,Ends[1]);
  391.         Screen.HorizLine(succ(X1),pred(X2),Y1,Att,S); {1.00c}
  392.         Screen.WriteAt(X2,Y1,Att,Ends[2]);
  393.         Screen.WindowOn;
  394.      end;
  395.    end; {DrawLine}
  396.  
  397. begin
  398.    Temp := ItemPtr(Item);
  399.    if Temp = nil then
  400.       exit;
  401.    Txt := GetText(Temp);
  402.    if Txt = '-' then
  403.       DrawLine(1)
  404.    else if Txt = '=' then
  405.       DrawLine(2)
  406.    else
  407.    begin 
  408.       if Temp^.Active then
  409.       begin
  410.          if Hi then
  411.          begin
  412.             Hot := vMenuHiHot;
  413.             Norm := vMenuHiNorm;
  414.          end
  415.          else
  416.          begin
  417.             Hot := vMenuLoHot;
  418.             Norm := vMenuLoNorm;
  419.          end;
  420.       end
  421.       else
  422.       begin
  423.          Hot := vMenuoff;
  424.          Norm := vMenuoff;
  425.       end; 
  426.       Txt := AddPre(Txt,Hi);
  427.       if Temp^.Submenu <> nil then
  428.          Txt := Txt + #16;
  429.       Txt := AddSuf(Txt,Hi);
  430.       Screen.WriteHi(succ(vGap),Item,Hot,Norm,Txt);
  431.       if Msg then               {clear or display message}
  432.          ChangeMessage(Item,Hi);
  433.       if Hi then
  434.       begin
  435.          Screen.gotoxy(succ(vGap),Item);
  436.          vPickOff := false;
  437.       end;
  438.    end;
  439. end; {WinMenuOBJ.DisplayItem}
  440.  
  441. procedure WinMenuOBJ.DrawEngine(eX,eY:byte);
  442. {}
  443. var
  444.   Width,Depth: byte;
  445.   X,Y: byte;
  446.   Temp: MenuItemPtr;
  447. begin
  448.    Temp := ItemPtr(vActiveItem);                 {1.10b}
  449.    if (Temp = nil) or (ItemPtr(vActiveItem)^.Active = false) then
  450.       vActiveItem := FirstActiveItem;
  451.    if not vWinSaved then
  452.    begin
  453.       vWinSaved := true;
  454.       Width := 2*vGap+vWidth+ ord(LookTOT^.ListLeftChar <> #0)
  455.                             + ord(LookTOT^.ListRightChar <> #0)
  456.                             + 2*ord(vStyle<> 0);
  457.       case vStyle of
  458.       0: Depth := vTotalItems;
  459.       6: Depth := vTotalItems + 4;
  460.       else Depth := vTotalItems + 2;
  461.       end; {case}
  462.       if eX = 0 then {center menu}
  463.          X := (Monitor^.Width - Width) div 2
  464.       else if eX + Width > Monitor^.Width then
  465.          X := Monitor^.Width - Width
  466.       else
  467.          X := eX;
  468.       if eY = 0 then {center menu}
  469.          Y := (Monitor^.Depth - Depth) div 2
  470.       else if eY + Depth > Monitor^.Depth then
  471.          Y := Monitor^.Depth - Depth
  472.       else
  473.          Y := eY;
  474.       if (vX <> 0) and (vY <> 0) then            {1.00f}
  475.          Win^.SetSize(vX,vY,pred(vX)+Width,pred(vY)+Depth,vStyle)
  476.       else
  477.          Win^.SetSize(X,Y,pred(X)+Width,pred(Y)+Depth,vStyle);
  478.       Win^.Draw;
  479.       Screen.Clear(vMenuLoNorm,' ');
  480.       DisplayAllItems;
  481.    end
  482.    else if not vUsedInPull then
  483.    begin
  484.       Screen.Clear(vMenuLoNorm,' ');
  485.       DisplayAllItems;
  486.    end;
  487. end; {WinMenuOBJ.DrawEngine}
  488.  
  489. procedure WinMenuOBJ.Draw;
  490. {}
  491. begin
  492.    DrawEngine(vX,vY);
  493. end; {WinMenuOBJ.Draw}
  494.  
  495. procedure WinMenuOBJ.Remove;
  496. {}
  497. begin
  498.    if (ItemPtr(vActiveItem) <> nil)
  499.    and (ItemPtr(vActiveItem)^.SubMenu <> nil) then
  500.       ItemPtr(vActiveItem)^.SubMenu^.Remove;
  501.    ChangeMessage(vActiveItem,false);
  502.    vSubActive := false;
  503.    vPickOff := true;
  504.    Win^.Remove;
  505.    vWinSaved := false;
  506. end; {WinMenuOBJ.Remove}
  507.  
  508. procedure WinMenuOBJ.MoveUp;
  509. {}
  510. var 
  511.   NewItem: byte;
  512.   Txt: StrVisible;
  513. begin
  514.    if (vActiveItem > 0) and (vActiveItem <= vTotalItems) then {1.00b}
  515.    begin
  516.       NewItem := vActiveItem;
  517.       repeat
  518.          dec(NewItem);
  519.          if NewItem = 0 then
  520.             NewItem := vTotalItems;
  521.          Txt := GetText(ItemPtr(NewItem));
  522.       until (NewItem = vActiveItem)
  523.       or    (     (Txt <> '')
  524.               and (Txt <> '=')
  525.               and (Txt <> '-')
  526.               and (ItemPtr(NewItem)^.Active = true) );
  527.       ChangeActiveItem(NewItem);
  528.    end;
  529. end; {WinMenuOBJ.MoveUp}
  530.  
  531. procedure WinMenuOBJ.MoveDown;
  532. {}
  533. var
  534.   NewItem: byte;
  535.   Txt: StrVisible;
  536. begin
  537.    if (vActiveItem > 0) and (vActiveItem <= vTotalItems) then {1.00b}
  538.    begin
  539.       NewItem := vActiveItem;
  540.       repeat
  541.          inc(NewItem);
  542.          if NewItem > vTotalItems then
  543.             NewItem := 1;
  544.          Txt := GetText(ItemPtr(NewItem));
  545.       until (NewItem = vActiveItem)
  546.       or    (     (Txt <> '')
  547.               and (Txt <> '=')
  548.               and (Txt <> '-')
  549.               and (ItemPtr(NewItem)^.Active = true) );
  550.       ChangeActiveItem(NewItem);
  551.    end;
  552. end; {WinMenuOBJ.MoveDown}
  553.  
  554. procedure WinMenuOBJ.MoveHome;
  555. {}
  556. var
  557.   NewItem: byte;
  558.   Txt: StrVisible;
  559. begin
  560.    if vActiveItem <> 1 then
  561.    begin
  562.       NewItem := 1;
  563.       Txt := GetText(ItemPtr(NewItem));
  564.       if (ItemPtr(NewItem)^.Active = false) 
  565.       or (Txt = '')
  566.       or (Txt = '=')
  567.       or (Txt = '-') then
  568.       begin
  569.          DisplayItem(vActiveItem,false,true);
  570.          vActiveItem := 1;
  571.          MoveDown;
  572.       end
  573.       else
  574.         ChangeActiveItem(NewItem);
  575.    end;
  576. end; {WinMenuOBJ.MoveHome}
  577.  
  578. procedure WinMenuOBJ.MoveEnd;
  579. {}
  580. var 
  581.   NewItem: byte;
  582.   Txt: StrVisible;
  583. begin
  584.    if vActiveItem <> vTotalItems then
  585.    begin
  586.       NewItem := vTotalItems;
  587.       Txt := GetText(ItemPtr(NewItem));
  588.       if (ItemPtr(NewItem)^.Active = false) 
  589.       or (Txt = '')
  590.       or (Txt = '=')
  591.       or (Txt = '-') then
  592.       begin
  593.          DisplayItem(vActiveItem,false,true);
  594.          vActiveItem := vTotalItems;
  595.          MoveUp;
  596.       end
  597.       else
  598.          ChangeActiveItem(NewItem);
  599.    end;
  600. end; {WinMenuOBJ.MoveEnd}
  601.  
  602. function WinMenuOBJ.TargetPick(X,Y:byte): byte;
  603. {}
  604. var 
  605.    X1,Y1,X2,Y2,Style: byte;
  606.    Temp: MenuItemPtr;
  607.    Txt: StrVisible;
  608. begin
  609.    TargetPick := 0;
  610.    Win^.GetSize(X1,Y1,X2,Y2,Style);
  611.    if ((Style=0) and (X in [X1..X2]) and (Y in [Y1..Y2]))
  612.    or ((Style=6) and (X in [succ(X1)..pred(X2)]) and (Y in [Y1+3..pred(Y2)]))
  613.    or ((Style <> 0) and (Style <> 6) and  (X in [succ(X1)..pred(X2)]) and (Y in [succ(Y1)..pred(Y2)]))
  614.    then
  615.    begin
  616.       case Style of 
  617.          0: dec(Y,pred(Y1));
  618.          6: dec(Y,(Y1+2));
  619.          else dec(Y,Y1);
  620.       end; {case}
  621.       Temp := ItemPtr(Y);
  622.       if (Temp <> nil) then
  623.       begin
  624.          Txt := GetText(Temp);
  625.          if (Temp^.Active = true) 
  626.          and (Txt <> '')
  627.          and (Txt <> '=')
  628.          and (Txt <> '-') then
  629.              TargetPick := Y;
  630.       end;
  631.    end;
  632. end; {WinMenuOBJ.TargetPick}
  633.  
  634. function WinMenuOBJ.MousePressed(X,Y:byte):boolean;
  635. {}
  636. var 
  637.    NewItem:byte;
  638.    Left,Center,Right : boolean;
  639.    X1,Y1,X2,Y2,style: byte;
  640. begin
  641.    NewItem := TargetPick(X,Y);
  642.    if NewItem <> 0 then
  643.    begin
  644.       ChangeActiveItem(NewItem);
  645.       Win^.GetSize(X1,Y1,X2,Y2,style);
  646.       repeat
  647.          Mouse.Status(Left,Center,Right,X,Y);
  648.          if Left then
  649.          begin
  650.             if vUsedInPull 
  651.             and ((X < X1) or (X > X2) or (Y < Y1) or (Y > Y2)) then
  652.             begin
  653.                MousePressed := false;
  654.                TurnPickOff;
  655.                exit;
  656.             end;
  657.             NewItem := TargetPick(X,Y);
  658.             if NewItem <> 0 then
  659.                ChangeActiveItem(NewItem);
  660.          end;
  661.       until not Left;
  662.       MousePressed := true;
  663.    end   
  664.    else
  665.       MousePressed := false;
  666. end; {WinMenuOBJ.MousePressed}
  667.  
  668. function WinMenuOBJ.ProcessKey(K:word; X,Y:byte):word;
  669. {}
  670. var
  671.    EscapeOn: boolean;
  672.    Finished: boolean;
  673.    HotKey: boolean;
  674.    Sub: BaseMenuPtr;
  675.    Choice: word;
  676.    SubX,SubY: byte;
  677.    X1,Y1,X2,Y2,style: byte;
  678. begin
  679.    if ItemPtr(vActiveItem) = nil then
  680.       Sub := nil
  681.    else
  682.       Sub := ItemPtr(vActiveItem)^.SubMenu;
  683.    if (Sub <> nil) and vSubActive then
  684.    begin
  685.       Choice := Sub^.ProcessKey(K,X,Y);
  686.       if (Choice = DriftID) and vUsedInPull then
  687.       begin
  688.          Mouse.Location(X,Y);
  689.          Win^.GetSize(X1,Y1,X2,Y2,style);
  690.          if (X >= X1) and (X <= X2) and (Y >= Y1) and (Y <= Y2) then
  691.             Choice := EscapeID;
  692.       end;
  693.       if (Choice = EscapeID) then
  694.       begin
  695.          Choice := 0;
  696.          Sub^.Remove;
  697.          vSubActive := false;
  698.          ChangeMessage(vActiveItem,true); {1.10a}
  699.       end;
  700.    end
  701.    else
  702.    begin
  703.       Finished := false; {assume not finished}
  704.       HotKey := false;
  705.       Choice := 0;
  706.       if HotKeySelect(K) then
  707.          HotKey := true
  708.       else
  709.       begin
  710.          if K = vHelpKey then
  711.             HelpTask(GetID(vActiveItem))
  712.          else
  713.             case K of
  714.                600,
  715.                27: if vAllowEsc then
  716.                       Finished:= true;
  717.                13: Finished := true;
  718.                513: begin
  719.                   if vUsedInPull then
  720.                   begin
  721.                      Win^.GetSize(X1,Y1,X2,Y2,style);
  722.                      if (X < X1) or (X > X2) or (Y < Y1) or (Y > Y2) then
  723.                      begin
  724.                         Choice := DriftID;
  725.                         TurnPickOff;
  726.                      end
  727.                      else
  728.                         Finished := MousePressed(X,Y);
  729.                   end
  730.                   else
  731.                      Finished := MousePressed(X,Y);
  732.                end;
  733.                328,584: MoveUp; {1.00g}
  734.                336,592: MoveDown;
  735.                327: MoveHome;
  736.                335: MoveEnd;
  737.                331,589: if vUsedinPull then
  738.                        Choice := LeftID;
  739.                333,587: if vUsedinPull then
  740.                        Choice := RightID;
  741.             end; {case}
  742.       end;
  743.       if Hotkey or (((K = 13) or (K=513)) and Finished) then
  744.       begin
  745.          if ItemPtr(vActiveItem) = nil then
  746.             Sub := nil
  747.          else
  748.             Sub := ItemPtr(vActiveItem)^.SubMenu;
  749.          if Sub <> Nil then
  750.          begin
  751.             EscapeOn := Sub^.GetAllowEsc;
  752.             if not EscapeOn then
  753.                Sub^.SetAllowEsc(true);
  754.             SubX := succ(lo(windmin))+Screen.WhereX;
  755.             SubY := succ(system.hi(windmin))+Screen.WhereY;
  756.             if not vUsedInPull then
  757.             begin
  758.                inc(SubX,10);
  759.                inc(SubY,2);
  760.             end;
  761.             ChangeMessage(vActiveItem,false);
  762.             Sub^.DrawEngine(SubX,SubY);
  763.             if vUsedInPull then
  764.                vSubActive := true
  765.             else
  766.             begin
  767.                Choice := Sub^.Activate;
  768.                Sub^.Remove;
  769.             end;
  770.             if not EscapeOn then
  771.                Sub^.SetAllowEsc(false);
  772.          end
  773.          else
  774.          begin
  775.             Choice := GetID(vActiveItem);
  776.             if Choice = 0 then
  777.                Choice := vActiveItem;
  778.          end;
  779.       end
  780.       else if ((K = 27) or (K = 600)) and (Finished) then
  781.          Choice := EscapeID;
  782.    end;
  783.    ProcessKey := Choice;
  784. end; {WinMenuOBJ.ProcessKey}
  785.  
  786. function WinMenuOBJ.Activate: word;
  787. {}
  788. var
  789.   K: word;
  790.   X,Y: byte;
  791.   Choice: word;
  792. begin
  793.    if not vWinSaved then
  794.       Draw
  795.    else
  796.       ChangeMessage(vActiveItem,true);
  797.    if Monitor^.ColorOn then
  798.       Screen.CursOff;
  799.    repeat
  800.       with Key do
  801.       begin
  802.          GetInput;
  803.          K := LastKey;
  804.          X := LastX;
  805.          Y := LastY;
  806.       end;
  807.       Win^.WinKey(K,X,Y);
  808.       Choice := ProcessKey(K,X,Y);
  809.    until (Choice <> 0);
  810.    if Choice = EscapeID then
  811.       Activate := 0
  812.    else
  813.       Activate := Choice;
  814.    ChangeMessage(vActiveItem,false);
  815.    vLastKey := Key.LastKey;
  816. end; {WinMenuOBJ.Activate}
  817.  
  818. destructor WinMenuOBJ.Done;
  819. {}
  820. begin
  821.    BaseMenuOBJ.Done;
  822. end; {WinMenuOBJ.Done}
  823. {|||||||||||||||||||||||||||||||||||||||}
  824. {                                       }
  825. {     M e n u O B J   M E T H O D S     }
  826. {                                       }
  827. {|||||||||||||||||||||||||||||||||||||||}
  828. constructor MenuOBJ.Init;
  829. {}
  830. begin
  831.    WinMenuOBJ.Init;
  832.    New(vWin,Init);
  833.    vWin^.SetTitle('Menu');
  834.    with LookTOT^ do
  835.       vWin^.SetColors(MenuBor, MenuloNorm, MenuTit, MenuIcon);
  836. end; {MenuOBJ.Init}
  837.  
  838. function MenuOBJ.Win: WinPtr;
  839. {}
  840. begin
  841.    Win := vWin;
  842. end; {MenuOBJ.Win}
  843.  
  844. destructor MenuOBJ.Done;
  845. {}
  846. begin
  847.    WinMenuOBJ.Done;
  848.    Dispose(vWin,Done);
  849. end; {MenuOBJ.Done}
  850. {|||||||||||||||||||||||||||||||||||||||||||||||}
  851. {                                               }
  852. {     M o v e M e n u O B J   M E T H O D S     }
  853. {                                               }
  854. {|||||||||||||||||||||||||||||||||||||||||||||||}
  855. constructor MoveMenuOBJ.Init;
  856. {}
  857. begin
  858.    WinMenuOBJ.Init;
  859.    New(vWin,Init);
  860.    vWin^.SetTitle('Menu');
  861.    vWin^.SetTitle('Menu');
  862.    with LookTOT^ do
  863.       vWin^.SetColors(MenuBor, MenuloNorm, MenuTit, MenuIcon);
  864. end; {MoveMenuOBJ.Init}
  865.  
  866. function MoveMenuOBJ.Win: WinPtr;
  867. {}
  868. begin
  869.    Win := vWin;
  870. end; {MoveMenuOBJ.Win}
  871.  
  872. destructor MoveMenuOBJ.Done;
  873. {}
  874. begin
  875.    WinMenuOBJ.Done;
  876.    Dispose(vWin,Done);
  877. end; {MoveMenuOBJ.Done}
  878. {|||||||||||||||||||||||||||||||||||||||||||||}
  879. {                                             }
  880. {     B a r M e n u O B J   M E T H O D S     }
  881. {                                             }
  882. {|||||||||||||||||||||||||||||||||||||||||||||}
  883. constructor BarMenuOBJ.Init;
  884. {}
  885. begin
  886.    BaseMenuOBJ.Init;
  887.    vX := 1;
  888.    vY := 1;
  889.    vGap := 0;
  890. end; {BarMenuOBJ.Init}
  891.  
  892. function BarMenuOBJ.GetX(Item:byte): byte;
  893. {}
  894. var 
  895.    I : integer;
  896.    X : byte;
  897. begin
  898.    if Item = 1 then
  899.       GetX := vX
  900.    else
  901.    begin
  902.       X := vX + pred(Item)*vGap;
  903.       for I := 1 to pred(Item) do
  904.          inc(X,length(strip('A',Screen.HiMarker,GetText(ItemPtr(I)))));
  905.       GetX := X;
  906.    end;
  907. end; {BarMenuOBJ.GetX}
  908.  
  909. procedure BarMenuOBJ.DisplayItem(Item:byte;Hi,Msg:boolean);
  910. {}
  911. var
  912.    Hot,Norm: byte;
  913.    X: byte;
  914.    Temp: MenuItemPtr;
  915.    Txt: StrVisible;
  916.    WinWasActive: boolean;
  917. begin
  918.    WinWasActive := Screen.WindowOff;
  919.    Temp := ItemPtr(Item);
  920.    if Temp^.Active then
  921.       begin
  922.          if Hi then
  923.          begin
  924.             Hot := vMenuHiHot;
  925.             Norm := vMenuHiNorm;
  926.          end
  927.          else
  928.          begin
  929.             Hot := vMenuLoHot;
  930.             Norm := vMenuLoNorm;
  931.          end;
  932.       end
  933.       else
  934.       begin
  935.          Hot := vMenuoff;
  936.          Norm := vMenuoff;
  937.       end;
  938.    Txt := GetText(Temp);
  939.    Txt := AddPre(Txt,Hi);
  940.    Txt := AddSuf(Txt,Hi);
  941.    X := GetX(Item);
  942.    Screen.WriteHi(X,vY,Hot,Norm,Txt);
  943.    if Msg then               {clear or display message}
  944.       ChangeMessage(Item,Hi);
  945.    if WinWasActive then
  946.       Screen.WindowOn;
  947.    if Hi then
  948.       Screen.gotoxy(X,vY);
  949. end; {BarMenuOBJ.DisplayItem}
  950.  
  951. procedure BarMenuOBJ.DrawEngine(eX,eY:byte); 
  952. {}
  953. begin
  954.    Screen.SetWinIgnore(true);
  955.    Screen.PartClear(vX,vY,GetX(vTotalItems)+
  956.                           length(strip('A',Screen.HiMarker,GetText(ItemPtr(vTotalItems)))),
  957.                     vY,LookTOT^.MenuLoNorm,' ');
  958.    Screen.SetWinIgnore(false);
  959.    DisplayAllItems;
  960. end; {BarMenuOBJ.DrawEngine}
  961.  
  962. destructor BarMenuOBJ.Done;
  963. {}
  964. begin
  965.    BaseMenuOBJ.Done;
  966. end; {BarMenuOBJ.Done}
  967. {|||||||||||||||||||||||||||||||||||||||||||||||||}
  968. {                                                 }
  969. {     L o t u s M e n u O B J   M E T H O D S     }
  970. {                                                 }
  971. {|||||||||||||||||||||||||||||||||||||||||||||||||}
  972. constructor LotusMenuOBJ.Init;
  973. {}
  974. begin
  975.    BarMenuOBJ.Init;
  976.    vHKStack := nil;
  977.    vMsgX := 1;
  978.    vMsgY := 2;
  979.    vMenuBarVisible := false;
  980. end; {LotusMenuOBJ.Init}
  981.  
  982. procedure LotusMenuOBJ.Draw;
  983. {}
  984. var I: integer;
  985. begin
  986.    vMenuBarVisible := true;
  987.    Screen.PartClear(vX,vY,GetX(vTotalItems)+
  988.                     length(strip('A',Screen.HiMarker,GetText(ItemPtr(vTotalItems)))),
  989.                     vY,LookTOT^.MenuLoNorm,' ');
  990.    for I := 1 to vTotalItems do
  991.        DisplayItem(I,false,false);
  992. end; {LotusMenuOBJ.Draw}
  993.  
  994. procedure LotusMenuOBJ.SetSpecialKey(HK:word;ID:word);
  995. {}
  996. var Temp: BarHotKeyPtr;
  997. begin
  998.    if MemAvail >= sizeof(vHKStack^) then
  999.    begin
  1000.       if vHKStack = nil then
  1001.       begin
  1002.          getmem(vHkStack,sizeof(vHKStack^));
  1003.          Temp := vHKStack;
  1004.       end
  1005.       else
  1006.       begin
  1007.          Temp := vHKStack;
  1008.          while Temp^.NextNode <> nil do
  1009.              Temp := Temp^.NextNode;
  1010.          getmem(Temp^.NextNode,sizeof(vHKStack^));
  1011.          Temp := Temp^.NextNode;
  1012.       end;
  1013.       Temp^.HK := HK;
  1014.       Temp^.ID := ID;
  1015.       Temp^.NextNode := nil;
  1016.    end;
  1017. end; {LotusMenuOBJ.SetSpecialKey}
  1018.  
  1019. function LotusMenuOBJ.HotKeyID(HK:word):word;
  1020. {}
  1021. var Temp: BarHotKeyPtr;
  1022. begin
  1023.    Temp := vHKStack;
  1024.    while (Temp <> nil) and (HK <> Temp^.HK) do
  1025.       Temp := Temp^.NextNode;
  1026.    if Temp = nil then
  1027.       HotKeyID := 0 
  1028.    else
  1029.       HotKeyID := Temp^.ID;
  1030. end; {LotusMenuOBJ.HotKeyID}
  1031.  
  1032. function LotusMenuOBJ.GetHK(Item:byte):word;
  1033. {}
  1034. var Temp: MenuItemPtr;
  1035. begin
  1036.    Temp := ItemPtr(Item);
  1037.    if Temp <> nil then
  1038.       GetHK := Temp^.HK
  1039.    else
  1040.       GetHK := 0;
  1041. end; {LotusMenuOBJ.GetHK}
  1042.  
  1043. function LotusMenuOBJ.AltHKItem(K:word):word;
  1044. {}
  1045. var
  1046.   I : integer;
  1047. begin
  1048.    I := 1;
  1049.    if (K >= 97) and (K <= 122) then
  1050.       dec(K,32);
  1051.    while (I <= vTotalItems) and (AltKey(GetHK(I)) <> K) do
  1052.      inc(I);
  1053.    if (I > vTotalItems) or (ItemPtr(I)^.Active = false) then
  1054.       AltHKItem := 0
  1055.    else
  1056.       AltHKItem := I;
  1057. end; {LotusMenuOBJ.AltHKItem}
  1058.  
  1059. function LotusMenuOBJ.MenuKey(K:word; X,Y:byte): boolean;
  1060. {returns true if the key is recognized by the
  1061.  menu as a hotkey}
  1062. var Temp: word;
  1063. begin
  1064.    if (K = 513) and (TargetPick(X,Y) > 0) then
  1065.       MenuKey := true
  1066.    else
  1067.    begin
  1068.       Temp := AltHkItem(K);
  1069.       if Temp = 0 then
  1070.          Temp := HotKeyID(K);
  1071.       Menukey := (Temp <> 0);
  1072.    end;
  1073. end; {LotusMenuOBJ.MenuKey}
  1074.  
  1075. procedure LotusMenuOBJ.Remove;                 
  1076. {}
  1077. begin
  1078.    vMenuBarVisible := false;
  1079.    Screen.ClearText(vX,vY,Monitor^.Width,vY);
  1080.    ChangeMessage(vActiveItem,false);
  1081. end; {LotusMenuOBJ.Remove}
  1082.  
  1083. procedure LotusMenuOBJ.MoveLeft;
  1084. {}
  1085. var NewItem: byte;
  1086. begin
  1087.    NewItem := vActiveItem;
  1088.    repeat
  1089.       dec(NewItem);
  1090.       if NewItem < 1 then
  1091.          NewItem := vTotalItems;
  1092.    until (ItemPtr(NewItem)^.Active = true)
  1093.    or (NewItem = vActiveItem);
  1094.    ChangeActiveItem(NewItem);
  1095. end; {LotusMenuOBJ.MoveLeft}
  1096.  
  1097. procedure LotusMenuOBJ.MoveRight;
  1098. {}
  1099. var NewItem: byte;
  1100. begin
  1101.    NewItem := vActiveItem;
  1102.    repeat
  1103.       inc(NewItem);
  1104.       if NewItem > vTotalItems then
  1105.          NewItem := 1;
  1106.    until (ItemPtr(NewItem)^.Active = true)
  1107.    or (NewItem = vActiveItem);
  1108.    ChangeActiveItem(NewItem);
  1109. end; {LotusMenuOBJ.MoveRight}
  1110.  
  1111. procedure LotusMenuOBJ.MoveHome;
  1112. {}
  1113. var NewItem: byte;
  1114. begin
  1115.    if vActiveItem <> 1 then
  1116.    begin
  1117.       NewItem := 1;
  1118.       if (ItemPtr(NewItem)^.Active = false) then
  1119.       begin
  1120.          DisplayItem(vActiveItem,false,true);
  1121.          vActiveItem := 1;
  1122.          MoveRight;
  1123.       end
  1124.       else
  1125.          ChangeActiveItem(NewItem);
  1126.    end;
  1127. end; {LotusMenuOBJ.MoveHome}
  1128.  
  1129. procedure LotusMenuOBJ.MoveEnd;
  1130. {}
  1131. var NewItem: byte;
  1132. begin
  1133.    if vActiveItem <> vTotalItems then
  1134.    begin
  1135.       NewItem := vTotalItems;
  1136.       if (ItemPtr(NewItem)^.Active = false) then
  1137.       begin
  1138.          DisplayItem(vActiveItem,false,true);
  1139.          vActiveItem := vTotalItems;
  1140.          MoveLeft;
  1141.       end
  1142.       else
  1143.          ChangeActiveItem(NewItem);
  1144.    end;
  1145. end; {LotusMenuOBJ.MoveEnd}
  1146.                        
  1147. function LotusMenuOBJ.TargetPick(X,Y:byte): byte;
  1148. {}
  1149. var I : integer;
  1150. begin
  1151.    TargetPick := 0;
  1152.    if (Y = vY) and (X >= vX) then {at least on right line}
  1153.    begin
  1154.       I := 0;
  1155.       while I < vTotalItems do
  1156.       begin
  1157.          inc(I);
  1158.          if X <= GetX(I) + length(strip('A',Screen.HiMarker,GetText(ItemPtr(I)))) then
  1159.          begin
  1160.             TargetPick := I;
  1161.             if ItemPtr(I)^.Active = false then {1.00i}
  1162.                TargetPick := 0;
  1163.             exit;
  1164.          end;   
  1165.       end;
  1166.    end;
  1167. end; {LotusMenuOBJ.TargetPick}
  1168.  
  1169. function LotusMenuOBJ.MousePressed(X,Y:byte;var Choice:word):boolean;
  1170. {}
  1171. var 
  1172.   NewItem:byte;
  1173.   Left,Center,Right : boolean;
  1174.   Cleared: boolean;
  1175. begin
  1176.    NewItem := TargetPick(X,Y);
  1177.    if NewItem <> 0 then
  1178.    begin
  1179.       ChangeActiveItem(NewItem);
  1180.       Cleared := false;
  1181.       repeat
  1182.          Mouse.Status(Left,Center,Right,X,Y);
  1183.          if Left then
  1184.          begin
  1185.             NewItem := TargetPick(X,Y);
  1186.             if NewItem <> 0 then
  1187.             begin
  1188.                if (NewItem = vActiveItem) and cleared then
  1189.                    DisplayItem(vActiveItem,true,true)
  1190.                else
  1191.                   ChangeActiveItem(NewItem);
  1192.                Cleared := false;
  1193.             end
  1194.             else if not Cleared then
  1195.             begin
  1196.                DisplayItem(vActiveItem,false,true);
  1197.                Cleared := true;
  1198.             end;
  1199.          end;
  1200.       until not Left;
  1201.       if TargetPick(X,Y) <> 0 then
  1202.          MousePressed := true
  1203.       else
  1204.       begin
  1205.          MousePressed := false;
  1206.          Choice := DriftID
  1207.       end;
  1208.    end   
  1209.    else
  1210.       MousePressed := false;
  1211. end; {LotusMenuOBJ.MousePressed}
  1212.  
  1213. function LotusMenuOBJ.ProcessKey(K:word; X,Y:byte):word;
  1214. {}
  1215. var
  1216.    EscapeOn: boolean;
  1217.    Finished: boolean;
  1218.    HotKey: boolean;
  1219.    Sub: BaseMenuPtr;
  1220.    Choice: word;
  1221. begin
  1222.    Finished := false; {assume not finished}
  1223.    HotKey := false;
  1224.    Choice := AltHKItem(K);
  1225.    if Choice = 0 then
  1226.    begin
  1227.       if HotKeySelect(K) then
  1228.          HotKey := true
  1229.       else
  1230.       begin
  1231.          if K = 513 then
  1232.             Finished := MousePressed(X,Y,Choice)
  1233.          else if K = vHelpKey then
  1234.             HelpTask(GetID(vActiveItem))
  1235.          else
  1236.             case K of
  1237.                600,
  1238.                27: if vAllowEsc then
  1239.                       Finished:= true;
  1240.                13: Finished := true;
  1241.                331,589: MoveLeft;  {1.00g}
  1242.                333,587: MoveRight;
  1243.                327: MoveHome;
  1244.                335: MoveEnd;
  1245.             end; {case}
  1246.       end;
  1247.       if Hotkey or (((K = 13) or (K=513)) and Finished) then
  1248.       begin
  1249.          Sub := ItemPtr(vActiveItem)^.SubMenu;
  1250.          if Sub <> Nil then
  1251.          begin
  1252.             EscapeOn := Sub^.GetAllowEsc;
  1253.             if not EscapeOn then
  1254.                Sub^.SetAllowEsc(true);
  1255.             ChangeMessage(vActiveItem,false);
  1256.             DisplayItem(vActiveItem,false,true); {1.00k}
  1257.             Remove;   {1.00h}
  1258.             Sub^.DrawEngine(succ(lo(windmin))+Screen.WhereX,
  1259.                             succ(system.hi(windmin))+Screen.WhereY);
  1260.             Choice := Sub^.Activate;
  1261.             Sub^.Remove;
  1262.             if Choice = 0 then
  1263.                DrawEngine(0,0);
  1264.             if not EscapeOn then
  1265.                Sub^.SetAllowEsc(false);
  1266.          end
  1267.          else
  1268.          begin
  1269.             Choice := GetID(vActiveItem);
  1270.             if Choice = 0 then
  1271.                Choice := vActiveItem;
  1272.          end;
  1273.       end 
  1274.       else if ((K = 27) or (K = 600)) and (Finished) then
  1275.          Choice := EscapeID;
  1276.    end;
  1277.    ProcessKey := Choice; 
  1278. end; {LotusMenuOBJ.ProcessKey}
  1279.  
  1280. function LotusMenuOBJ.Activate: word;         
  1281. {}
  1282. begin
  1283.    Activate := Push(0,0,0);
  1284. end; {LotusMenuOBJ.Activate}
  1285.  
  1286. function LotusMenuOBJ.Push(K:word; X,Y: byte): word;         
  1287. {}
  1288. var
  1289.   Choice: word;
  1290.   FirstIteration,
  1291.   MVisible: boolean;
  1292.   CX,CY,CT,CB: byte;
  1293. begin
  1294.    MVisible := Mouse.Visible;
  1295.    if Monitor^.ColorOn then
  1296.       with Screen do
  1297.       begin
  1298.          CursSave;
  1299.          CX := WhereX;
  1300.          CY := WhereY;
  1301.          CT := CursTop;
  1302.          CB := CursBot;
  1303.          CursOff;
  1304.       end;
  1305.    DrawEngine(0,0);
  1306.    if not MVisible then
  1307.       Mouse.Show;
  1308.    FirstIteration := true;
  1309.    repeat
  1310.       if (FirstIteration = false) or ((K=0) and (X=0) and (Y=0)) then
  1311.          with Key do
  1312.          begin
  1313.             GetInput;
  1314.             K := LastKey;
  1315.             X := LastX;
  1316.             Y := LastY;
  1317.          end;
  1318.          Choice := ProcessKey(K,X,Y);
  1319.       FirstIteration := false;
  1320.    until (Choice <> 0);
  1321.    if Choice = EscapeID then
  1322.       Push := 0
  1323.    else
  1324.       Push := Choice;
  1325.    DisplayItem(vActiveItem,false,true);
  1326.    vLastKey := Key.LastKey;
  1327.    if not MVisible then
  1328.       Mouse.Hide;
  1329.    if Monitor^.ColorOn then
  1330.       with Screen do
  1331.       begin
  1332.          GotoXY(CX,CY);
  1333.          CursSize(CT,CB);
  1334.       end;
  1335. end; {LotusMenuOBJ.Push}
  1336.  
  1337. procedure LotusMenuOBJ.DisposeSpecialKeys;
  1338. {}
  1339. var Temp1, Temp2:BarHotKeyPtr;
  1340. begin
  1341.    if vHKStack <> nil then
  1342.    begin
  1343.       Temp1 := vHkStack;
  1344.       Temp2 := vHkStack;
  1345.       while Temp2 <> nil do
  1346.       begin
  1347.           Temp1 := Temp2;
  1348.           Temp2 := Temp2^.NextNode;
  1349.           freemem(Temp1,sizeof(Temp1^));
  1350.       end; 
  1351.       vHKStack := nil;
  1352.    end;
  1353. end; {LotusMenuOBJ.DisposeSpecialKeys}
  1354.  
  1355. destructor LotusMenuOBJ.Done;
  1356. {}
  1357. begin
  1358.    BarMenuOBJ.Done;
  1359.    DisposeSpecialKeys;
  1360. end; {LotusMenuOBJ.Done}
  1361. {|||||||||||||||||||||||||||||||||||||||||||||||}
  1362. {                                               }
  1363. {     P u l l M e n u O B J   M E T H O D S     }
  1364. {                                               }
  1365. {|||||||||||||||||||||||||||||||||||||||||||||||}
  1366. constructor PullMenuOBJ.Init;
  1367. {}
  1368. begin
  1369.    LotusMenuOBJ.Init;
  1370.    vMenuDown := false;
  1371.    vX := 2;
  1372.    vY := 1;
  1373.    vMsgX := 11;
  1374.    vMsgY := Monitor^.Depth;
  1375. end; {PullMenuOBJ.Init}
  1376.  
  1377. procedure PullMenuOBJ.MoveLeft;
  1378. {}
  1379. var Sub: BaseMenuPtr;
  1380. begin
  1381.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1382.    if vMenuDown and (Sub <> nil) then
  1383.       Sub^.Remove;
  1384.    LotusMenuOBJ.MoveLeft;
  1385. end; {PullMenuOBJ.MoveLeft}
  1386.  
  1387. procedure PullMenuOBJ.MoveRight;
  1388. {}
  1389. var Sub: BaseMenuPtr;
  1390. begin
  1391.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1392.    if vMenuDown and (Sub <> nil) then
  1393.       Sub^.Remove;
  1394.    LotusMenuOBJ.MoveRight;
  1395. end; {PullMenuOBJ.MoveRight}
  1396.  
  1397. procedure PullMenuOBJ.MoveHome;
  1398. {}
  1399. var Sub: BaseMenuPtr;
  1400. begin
  1401.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1402.    if vMenuDown and (Sub <> nil) then
  1403.       Sub^.Remove;
  1404.    LotusMenuOBJ.MoveHome;
  1405. end; {PullMenuOBJ.MoveHome}
  1406.  
  1407. procedure PullMenuOBJ.MoveEnd;
  1408. {}
  1409. var Sub: BaseMenuPtr;
  1410. begin
  1411.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1412.    if vMenuDown and (Sub <> nil) then
  1413.       Sub^.Remove;
  1414.    LotusMenuOBJ.MoveEnd;
  1415. end; {PullMenuOBJ.MoveEnd}
  1416.  
  1417. function PullMenuOBJ.MousePressed(X,Y:byte):boolean;
  1418. {}
  1419. var 
  1420.   NewItem:byte;
  1421.   Sub: BaseMenuPtr;
  1422. begin
  1423.    NewItem := TargetPick(X,Y);
  1424.    if (NewItem <> 0) then
  1425.    begin
  1426.       Sub := ItemPtr(vActiveItem)^.SubMenu;
  1427.       if (NewItem <> vActiveItem) then
  1428.       begin
  1429.          if vMenuDown and (Sub <> nil) then
  1430.                Sub^.Remove;
  1431.          ChangeActiveItem(NewItem);
  1432.       end
  1433.       else if vMenuDown and (Sub <> nil) and (Sub^.GetPickOff = false) then {turn off sub pick}
  1434.       begin
  1435.            Sub^.TurnPickOff;
  1436.            ChangeMessage(vActiveItem,true);
  1437.       end;
  1438.       MousePressed := true;
  1439.    end   
  1440.    else
  1441.       MousePressed := false;
  1442. end; {PullMenuOBJ.MousePressed}
  1443.  
  1444. function PullMenuOBJ.ProcessKey(K:word; X,Y:byte):word;
  1445. {}
  1446. var
  1447.    Choice : word;
  1448.    Sub: BaseMenuPtr;
  1449.    Hotkey, L,C,R,Temp: boolean;
  1450.    LastActiveItem : byte;
  1451.    Xval,Yval : integer; {1.1}
  1452. begin
  1453.    Hotkey := false;
  1454.    Choice := AltHKItem(K);
  1455.    LastActiveItem := vActiveItem;
  1456.    {HotKeyHook}
  1457.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1458.    if Choice <> 0 then
  1459.    begin
  1460.       if (Choice <> vActiveItem) then
  1461.       begin
  1462.          if vMenuDown and (Sub <> nil) then
  1463.             Sub^.Remove;
  1464.          ChangeActiveItem(Choice);
  1465.       end;
  1466.       Sub := ItemPtr(vActiveItem)^.SubMenu;
  1467.       if Sub <> nil then
  1468.       begin
  1469.          Choice := 0;
  1470.          vMenuDown := true;
  1471.          vSubActive := true;
  1472.       end
  1473.       else
  1474.       begin
  1475.          Choice := GetID(vActiveItem);
  1476.          if Choice = 0 then
  1477.             Choice := vActiveItem;
  1478.       end;
  1479.    end
  1480.    else     {no hotkey pressed}
  1481.    begin
  1482.       if (K = 513) and (TargetPick(X,Y) <> 0) then
  1483.       begin
  1484.          vMenuDown := true;
  1485.          vSubActive := true;
  1486.          if not vMsgVisible then
  1487.             ChangeMessage(vActiveItem,true);
  1488.          Sub := ItemPtr(TargetPick(X,Y))^.SubMenu;   {1.00a}
  1489.       end;
  1490.       if Sub = nil then
  1491.          vSubActive := false
  1492.       else if vMenuDown then
  1493.          vSubActive := true;
  1494.       if (vSubActive) then
  1495.       begin
  1496.          if (K <> 513) then
  1497.          begin
  1498.             Choice := Sub^.ProcessKey(K,X,Y);
  1499.             if Choice = LeftID then
  1500.             begin
  1501.                MoveLeft;
  1502.                Choice := 0;
  1503.             end
  1504.             else if choice = RightID then
  1505.             begin
  1506.                MoveRight;
  1507.                Choice := 0;
  1508.             end
  1509.  
  1510.          end
  1511.          else {if (K=513) then }
  1512.          begin
  1513.             if Sub^.MenuZone(X,Y) then
  1514.             begin
  1515.                {clear main message}
  1516.                ChangeMessage(vActiveItem,false);
  1517.                Choice := Sub^.ProcessKey(K,X,Y)
  1518.             end
  1519.             else
  1520.             begin
  1521.                Temp := MousePressed(X,Y);
  1522.                if not Temp then
  1523.                begin
  1524.                   Mouse.Status(L,C,R,X,Y);
  1525.                   if not L then
  1526.                      Choice := EscapeID
  1527.                   else
  1528.                      ChangeMessage(VActiveItem,true);
  1529.                end;
  1530.             end;
  1531.          end;
  1532.       end
  1533.       else  {not sub active}
  1534.       begin
  1535.          if HotKeySelect(K) then
  1536.          begin
  1537.             HotKey := true;
  1538.             Sub := ItemPtr(vActiveItem)^.SubMenu;       {1.00a}
  1539.          end
  1540.          else
  1541.          begin
  1542.             case K of
  1543.                513: Temp := MousePressed(X,Y);
  1544.                331,589: MoveLeft;  {1.00g}
  1545.                333,587: MoveRight;
  1546.                327: MoveHome;
  1547.                335: MoveEnd;
  1548.             end; {case}
  1549.          end;
  1550.          if ((K= 27) and vAllowEsc) then
  1551.             Choice := EscapeID
  1552.          else if HotKey or (K = 13) or (K=513) then
  1553.          begin
  1554.             if Sub <> nil then
  1555.             begin
  1556.                vMenuDown := true;
  1557.                ChangeMessage(vActiveItem,false);                      {1.00d}
  1558.                Sub^.DrawEngine(pred(Screen.WhereX),succ(Screen.WhereY));
  1559.                if K = 13 then
  1560.                   vSubActive := true
  1561.                else
  1562.                   vSubActive := false;
  1563.             end
  1564.             else
  1565.             begin
  1566.                Mouse.Status(L,C,R,X,Y);
  1567.                if (K = 13) or ((K=513) and (L=false)) or Hotkey then  {1.00a}
  1568.                begin
  1569.                   Choice := GetID(vActiveItem);
  1570.                   if Choice = 0 then
  1571.                      Choice := vActiveItem;
  1572.                end;
  1573.             end;
  1574.          end;
  1575.       end;
  1576.    end;
  1577.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1578.    if vMenuDown and (Sub <> nil) then
  1579.    begin
  1580.       if (LastActiveItem <> vActiveItem) and (K<> 513) and (Hotkey = false) then {1.00e}
  1581.          ChangeMessage(vActiveItem,false);
  1582.       Yval := succ(Screen.WhereY);
  1583.       if (YVal < 0) or (YVal > 255) then
  1584.          YVal := 255;
  1585.       XVal := pred(Screen.WhereX);
  1586.       Sub^.DrawEngine(XVal,YVal);
  1587.    end;
  1588.    if (K = 513) then
  1589.    begin
  1590.       Mouse.Status(L,C,R,X,Y);
  1591.       if not L then
  1592.       begin
  1593.          if (Sub <> nil) and (Sub^.GetSubActive = false) then
  1594.          begin
  1595.             ChangeMessage(vActiveItem,false);
  1596.             Sub^.DisplayItem(Sub^.GetActiveItem,true,true);
  1597.          end;
  1598.       end;
  1599.    end;
  1600.    ProcessKey := Choice;
  1601. end; {PullMenuOBJ.ProcessKey}
  1602.  
  1603. function PullMenuOBJ.Activate: word;         
  1604. {}
  1605. begin
  1606.    Activate := Push(0,0,0);
  1607. end; {PullMenuOBJ.Activate}
  1608.  
  1609. function PullMenuOBJ.Push(K:word; X,Y:byte): word;
  1610. {}
  1611. var
  1612.    Choice: word;
  1613.    MVisible: boolean;
  1614.    FirstIteration: boolean;
  1615.    CX,CY,CT,CB:byte;
  1616. begin
  1617.    vSubActive := false;
  1618.    vMenuDown := false;
  1619.    MVisible := Mouse.Visible;
  1620.    if Monitor^.ColorOn then
  1621.       with Screen do
  1622.       begin
  1623.          CursSave;
  1624.          CX := WhereX;
  1625.          CY := WhereY;
  1626.          CT := CursTop;
  1627.          CB := CursBot;
  1628.          CursOff;
  1629.       end;
  1630.    if not vMenuBarVisible then
  1631.       DrawEngine(0,0);
  1632.    if not MVisible then
  1633.       Mouse.Show;
  1634.    FirstIteration := true;
  1635.    repeat
  1636.       if (FirstIteration = false) or ((K=0) and (X=0) and (Y=0)) then
  1637.          with Key do
  1638.          begin
  1639.             GetInput;
  1640.             K := LastKey;
  1641.             X := LastX;
  1642.             Y := LastY;
  1643.          end;
  1644.       if (K = vHelpKey) and (vMenuDown = false) then
  1645.       begin
  1646.          HelpTask(GetHelpID);
  1647.          Choice := 0;
  1648.       end
  1649.       else 
  1650.       begin
  1651.          Choice := HotKeyID(K);
  1652.          (*
  1653.          Choice := 0;
  1654.          *)
  1655.          if Choice = 0 then
  1656.             Choice := ProcessKey(K,X,Y);
  1657.       end;
  1658.       FirstIteration := false;
  1659.    until (Choice <> 0) and (Choice <> DriftID);
  1660.    if Choice = EscapeID then
  1661.       Push := 0
  1662.    else
  1663.       Push := Choice;
  1664.    ChangeMessage(vActiveItem,false);
  1665.    if vSubActive and (ItemPtr(vActiveItem)^.SubMenu <> nil) then
  1666.       ItemPtr(vActiveItem)^.SubMenu^.Remove;
  1667.    DisplayItem(vActiveItem,false,false);
  1668.    vLastKey := Key.LastKey;
  1669.    if not MVisible then
  1670.       Mouse.Hide;
  1671.    if Monitor^.ColorOn then
  1672.       with Screen do
  1673.       begin
  1674.          GotoXY(CX,CY);
  1675.          CursSize(CT,CB);
  1676.       end;
  1677. end; {PullMenuOBJ.Push}
  1678.  
  1679. destructor PullMenuOBJ.Done;
  1680. {}
  1681. begin
  1682.    LotusMenuOBJ.Done;
  1683. end; {PullMenuOBJ.Done}
  1684. {|||||||||||||||||||||||||||||||||||||||||||}
  1685. {                                           }
  1686. {     E Z P u l l O B J   M E T H O D S     }
  1687. {                                           }
  1688. {|||||||||||||||||||||||||||||||||||||||||||}
  1689. constructor EZPullOBJ.Init;
  1690. {}
  1691. begin
  1692.    new(vTopBar,Init);
  1693.    vSubMenuStack := nil;
  1694.    vListAssigned := false;
  1695.    vTotalSubs := 0;
  1696. end; {EZPullOBJ.Init}
  1697.  
  1698. function EZPullOBJ.MainMenu:pPullMenuOBJ;
  1699. {}
  1700. begin
  1701.    MainMenu := vTopBar;
  1702. end; {EZPullOBJ.MainMenu}
  1703.  
  1704. function EZPullOBJ.SubMenu(MenuNumber: byte):SubMenuPtr;
  1705. {}
  1706. var 
  1707.   Temp: SubMenuListPtr;
  1708.   I : integer;
  1709. begin
  1710.    if (MenuNumber < 1) or (MenuNumber > vTotalSubs) then
  1711.       Submenu := nil
  1712.    else
  1713.    begin
  1714.       Temp := vSubMenuStack;
  1715.       for I := 2 to MenuNumber do
  1716.          if Temp <> nil then
  1717.             Temp := Temp^.NextMenu;
  1718.       SubMenu := Temp^.SubMenu;
  1719.    end;
  1720. end; {EZPullOBJ.SubMenu}
  1721.  
  1722. function EZPullOBJ.Activate: word;       
  1723. {}
  1724. begin
  1725.    if vListAssigned = false then
  1726.       Activate := 0
  1727.    else
  1728.       Activate := MainMenu^.Activate;
  1729. end; {EZPullOBJ.Activate}
  1730.  
  1731. function EZPullOBJ.Push(K:word; X,Y:byte): word;       
  1732. {}
  1733. begin
  1734.    if vListAssigned = false then
  1735.       Push := 0
  1736.    else
  1737.       Push := MainMenu^.Push(K,X,Y);
  1738. end; {EZPullOBJ.Activate}
  1739.  
  1740. procedure EZPullOBJ.BuildMenu;
  1741. {}
  1742. var
  1743.    Txt: StrVisible;
  1744.    Msg: StrVisible;
  1745.    HK: word;
  1746.    SpecialHK: word;
  1747.    ID: word;
  1748.    Active: boolean;
  1749.    I: integer;
  1750.  
  1751.    procedure ParseItemInfo(Str:String;BakID:word);
  1752.    {}
  1753.    var 
  1754.       P : byte;
  1755.       IDStr: StrVisible;
  1756.    begin
  1757.       Txt := '';
  1758.       Msg := '';
  1759.       HK := 0;
  1760.       SpecialHK := 0;
  1761.       Active := true;
  1762.       P := pos(EZSeparator,Str);
  1763.       if P = 0 then
  1764.          Txt := Str
  1765.       else
  1766.       begin
  1767.          Txt := copy(Str,1,pred(p));
  1768.          Msg := copy(Str,succ(P),255);
  1769.          P := pos(EZSeparator,Msg);
  1770.          if P <> 0 then
  1771.          begin
  1772.             IDStr := copy(Msg,succ(P),255);
  1773.             delete(Msg,P,255);
  1774.             P := pos(EZSeparator,IDStr);
  1775.             if P = 0 then
  1776.                ID := StrToInt(IDStr)
  1777.             else
  1778.             begin
  1779.                ID := StrtoInt(copy(IDStr,1,pred(P)));
  1780.                SpecialHK := StrtoInt(copy(IDStr,succ(P),255));
  1781.             end;
  1782.          end
  1783.          else
  1784.             ID := BakID;
  1785.       end;
  1786.       if (Txt <> '') and (Txt[1] = EZInActive) then
  1787.       begin
  1788.          Active := false;
  1789.          delete(Txt,1,1);
  1790.       end;
  1791.       P := pos(Screen.HiMarker,Txt);
  1792.       if P <> 0 then
  1793.          HK := ord(upcase(Txt[succ(p)]));
  1794.    end; {ParseItemInfo}
  1795.  
  1796.    procedure BuildMenuBar;
  1797.    {}
  1798.    var 
  1799.      Str:string;
  1800.      I : integer;
  1801.    begin
  1802.       Str := GetString(1);
  1803.       if (Str = '') then
  1804.          Str := 'Guess';
  1805.       if (Str[1] = EZNewBarItem) then
  1806.          delete(Str,1,1);
  1807.       ParseItemInfo(Str,1);
  1808.       Mainmenu^.AddFullItem(Txt,ID,HK,Msg,nil);
  1809.       if SpecialHK <> 0 then
  1810.          Mainmenu^.SetSpecialKey(SpecialHK,ID);
  1811.       if not Active then
  1812.          Mainmenu^.SetStatus(1,false);
  1813.       inc(vTotalSubs);  
  1814.       for I := 2 to TotalStrings do
  1815.       begin
  1816.          Str := GetString(I);
  1817.          if (Str <> '') and (Str[1] = EZNewBarItem) then
  1818.          begin
  1819.             delete(Str,1,1);
  1820.             ParseItemInfo(Str,I);
  1821.             Mainmenu^.AddFullItem(Txt,ID,HK,Msg,nil);
  1822.             if SpecialHK <> 0 then
  1823.                Mainmenu^.SetSpecialKey(SpecialHK,ID);
  1824.             if not Active then
  1825.                Mainmenu^.SetStatus(I,false);
  1826.             inc(vTotalSubs);  
  1827.          end;
  1828.       end;
  1829.    end; {BuildMenuBar}
  1830.  
  1831.    procedure BuildSubMenuList;
  1832.    {}
  1833.    var 
  1834.      I: integer;
  1835.      Temp: SubMenuListPtr; 
  1836.    begin
  1837.       if MemAvail < vTotalSubs*sizeof(SubMenuList) then
  1838.          Error(1)
  1839.       else
  1840.       begin
  1841.          getmem(vSubMenuStack,sizeof(vSubMenuStack^));
  1842.          vSubMenuStack^.NextMenu := nil;
  1843.          vSubMenuStack^.SubMenu := nil;
  1844.          Temp := vSubMenuStack;
  1845.          for I := 2 to vTotalSubs do
  1846.          begin
  1847.             getmem(Temp^.NextMenu,sizeof(vSubMenuStack^));
  1848.             Temp := Temp^.Nextmenu;
  1849.             Temp^.SubMenu := nil;
  1850.          end;
  1851.          Temp^.NextMenu := nil;
  1852.       end;
  1853.    end; {BuildSubMenuList}
  1854.  
  1855.    procedure CreateSubMenu(SubCounter:byte);
  1856.    {}
  1857.    var 
  1858.       Temp: SubMenuListPtr;
  1859.       I : integer;
  1860.    begin
  1861.       Temp := vSubMenuStack;
  1862.       for I := 2 to SubCounter do
  1863.           Temp := Temp^.NextMenu;
  1864.       new(Temp^.Submenu,Init);
  1865.       Temp^.Submenu^.SetForPull;
  1866.    end; {CreateSubMenu}
  1867.  
  1868.    procedure BuildSubMenus;
  1869.    {}
  1870.    var 
  1871.      Str:string;
  1872.      I : integer;
  1873.      SubCreated: boolean;
  1874.      SubCounter: byte;
  1875.      PickCounter : byte;
  1876.    begin
  1877.       SubCreated := false;
  1878.       SubCounter := 1;
  1879.       for I := 2 to TotalStrings do
  1880.       begin
  1881.          Str := GetString(I);
  1882.          if (Str <> '') then
  1883.          begin
  1884.             if (Str[1] = EZNewBarItem) then
  1885.             begin
  1886.                with SubMenu(SubCounter)^ do
  1887.                   SetActiveItem(FirstActiveItem);
  1888.                SubCreated := false;
  1889.                inc(SubCounter);
  1890.             end
  1891.             else
  1892.             begin
  1893.                if not SubCreated then
  1894.                begin
  1895.                   SubCreated := true;
  1896.                   CreateSubMenu(SubCounter);
  1897.                   PickCounter := 0;
  1898.                end;
  1899.                ParseItemInfo(Str,I);
  1900.                SubMenu(SubCounter)^.AddFullItem(Txt,ID,HK,Msg,nil);
  1901.                inc(PickCounter);
  1902.                if SpecialHK <> 0 then
  1903.                   Mainmenu^.SetSpecialKey(SpecialHK,ID);
  1904.                if not Active then
  1905.                   SubMenu(SubCounter)^.SetStatus(PickCounter,false);
  1906.             end;
  1907.          end;
  1908.       end;
  1909.    end; {BuildSubMenus}
  1910.  
  1911. begin
  1912.    BuildMenuBar;
  1913.    BuildSubMenuList;
  1914.    BuildSubMenus;
  1915.    for I := 1 to  vTotalSubs do
  1916.       if SubMenu(I) <> nil then
  1917.          Mainmenu^.SetSubMenu(I,SubMenu(I));
  1918. end; {EZPullOBJ.BuildMenu}
  1919.  
  1920. function EZPullOBJ.GetString(Item: word):string;
  1921. {abstract}
  1922. begin
  1923.    GetString := '';
  1924. end; {EZPullOBJ.GetString}
  1925.  
  1926. function EZPullOBJ.TotalStrings: word;
  1927. {abstract} 
  1928. begin 
  1929.    TotalStrings := 0;
  1930. end; {EZPullOBJ.TotalStrings}
  1931.  
  1932. destructor EZPullOBJ.Done;       {1.00b}          
  1933. {}
  1934. var 
  1935.   Temp1,Temp2: SubMenuListPtr;
  1936.   I: integer;
  1937. begin
  1938.    Temp1 :=  vSubMenuStack;
  1939.    while (Temp1 <> nil) do
  1940.    begin
  1941.        Temp2 := Temp1^.NextMenu;
  1942.        if (Temp1^.SubMenu <> nil) then
  1943.        begin
  1944.           Dispose(Temp1^.SubMenu,Done);
  1945.        end;
  1946.        freemem(Temp1,sizeof(Temp1^));
  1947.        Temp1 := Temp2;
  1948.    end;
  1949.    dispose(vTopBar,Done);
  1950. end; {EZPullOBJ.Done}
  1951. {|||||||||||||||||||||||||||||||||||||||||||||||||||||}
  1952. {                                                     }
  1953. {     E Z P u l l A r r a y O B J   M E T H O D S     }
  1954. {                                                     }
  1955. {|||||||||||||||||||||||||||||||||||||||||||||||||||||}
  1956. constructor EZPullArrayOBJ.Init;
  1957. {}
  1958. begin
  1959.    EZPullOBJ.Init;
  1960. end; {EZPullArrayOBJ.Init}
  1961.  
  1962. procedure EZPullArrayOBJ.AssignList(var StrArray; Total:Longint; StrLength:byte);
  1963. {}
  1964. begin
  1965.    vArrayPtr := @StrArray;
  1966.    vStrLength := StrLength;
  1967.    vTotalItems := Total;
  1968.    vListAssigned := true;
  1969.    BuildMenu;
  1970. end; {EZPullArrayOBJ.AssignList}
  1971.  
  1972. function EZPullArrayOBJ.TotalStrings: word;                               
  1973. {}
  1974. begin
  1975.    TotalStrings := vTotalItems;
  1976. end; {EZPullArrayOBJ.TotalStrings}
  1977.  
  1978. function EZPullArrayOBJ.GetString(Item: word): string;                    
  1979. {}
  1980. var
  1981.   W : longint;
  1982.   TempStr : String;
  1983.   ArrayOffset: word;
  1984. begin
  1985.    {move array string to Temp}
  1986.    W := pred(Item) * succ(vStrLength);
  1987.    ArrayOffset := Ofs(vArrayPtr^) + W;
  1988.    Move(Mem[Seg(vArrayPtr^):ArrayOffset],TempStr,1);
  1989.    Move(Mem[Seg(vArrayPtr^):succ(ArrayOffset)],TempStr[1],ord(TempStr[0]));
  1990.    GetString := TempStr;
  1991. end; {EZPullArrayOBJ.GetString}
  1992.  
  1993. destructor EZPullArrayOBJ.Done;
  1994. {}
  1995. begin
  1996.    EZPullOBJ.Done;
  1997. end; {EZPullArrayOBJ.Done}
  1998. {|||||||||||||||||||||||||||||||||||||||||||||||||||}
  1999. {                                                   }
  2000. {     E Z P u l l L i n k O B J   M E T H O D S     }
  2001. {                                                   }
  2002. {|||||||||||||||||||||||||||||||||||||||||||||||||||}
  2003. constructor EZPullLinkOBJ.Init;
  2004. {}
  2005. begin
  2006.    EZPullOBJ.Init;
  2007. end; {EZPullLinkOBJ.Init}
  2008.  
  2009. procedure EZPullLinkOBJ.AssignList(var LinkList: DLLOBJ);
  2010. {}
  2011. begin
  2012.    vLinkList := @LinkList;
  2013.    vListAssigned := true;
  2014.    BuildMenu;
  2015. end; {EZPullLinkOBJ.AssignList}
  2016.  
  2017. function EZPullLinkOBJ.TotalStrings: word;              
  2018. {}
  2019. begin
  2020.    TotalStrings := vLinkList^.TotalNodes;
  2021. end; {EZPullLinkOBJ.TotalStrings}
  2022.  
  2023. function EZPullLinkOBJ.GetString(Item: word): string;   
  2024. {}
  2025. var TempPtr : DLLNodePtr;
  2026. begin
  2027.    TempPtr := vLinkList^.NodePtr(Item);
  2028.    if TempPtr <> Nil then
  2029.       vLinkList^.ShiftActiveNode(TempPtr,Item);
  2030.    GetString := vLinkList^.GetStr(TempPtr,0,255);
  2031. end; {EZPullLinkOBJ.GetString}
  2032.  
  2033. destructor EZPullLinkOBJ.Done;                            
  2034. {}
  2035. begin
  2036.    EZPullOBJ.Done;
  2037. end; {EZPullLinkOBJ.Done}
  2038. {|||||||||||||||||||||||||||||||||||||||||||||||}
  2039. {                                               }
  2040. {     U N I T   I N I T I A L I Z A T I O N     }
  2041. {                                               }
  2042. {|||||||||||||||||||||||||||||||||||||||||||||||}
  2043. procedure MenuInit;
  2044. {initilizes objects and global variables}
  2045. begin
  2046. end; {MenuInit}
  2047.  
  2048. {end of unit - add intialization routines below}
  2049. {$IFNDEF OVERLAY}
  2050. begin
  2051.    MenuInit;
  2052. {$ENDIF}
  2053. end.
  2054.  
  2055.  
  2056.